home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS02.ADF / Asm / SystemVprintf.asm < prev    next >
Assembly Source File  |  1989-05-30  |  31KB  |  1,083 lines

  1.    RORG   0
  2. *
  3. * Unix System 5 compatible printf, fprintf, sprintf functions, ported to
  4. * commodore Amiga,  12/17/85  Gary Sarff.  The only bug is that the
  5. * %f format specification may not work properly since Amiga lacks the
  6. * function  fcvt(), instead a call to ecvt is used.  It really should be
  7. * fixed to use gcvt() and perhaps a temporary buffer to make it "look" like
  8. * fcvt() but I don't have time now to do it.
  9. * The reason this port was done was that Lattice C's printf on the Amiga
  10. * lacks the ability to use an * as a field width or precision to allow
  11. * run-time specification of field width or precision.  These functions have
  12. * that capability.
  13. *
  14. * To use this from a C program, you must #include <stdio.h>  since these
  15. * functions use the address of the i/o buffer  __iob,
  16. * and you should declare these functions to be:
  17. *   extern int u5printf();
  18. *   extern int u5fprintf();
  19. *   extern int u5sprintf();
  20. * You may then call them with any arbitrary number of arguments, just like
  21. * the builtin printf, fprintf, sprintf functions.
  22. * You can also access the gcvt() function yourself by declaring it as
  23. *   extern char *gcvt();
  24. * and calling it with args:    gcvt(value, ndigits, buf);
  25. * where declarations           double value;
  26. *                              int ndigits; /* the number of digits shown*/
  27. *                              char *buf;  /* address of the buffer to
  28. *                                             store result in.  gcvt also
  29. *                                             returns the address of this
  30. *                                             buffer */
  31. * sccs_ctnrl == "5/15/81 (Berkley) @(#)printf.s   v3.8"
  32. *
  33. * This file had to be modified extensively in places to allow for the
  34. * difference in the structure of __iob on the Amiga from the Unix __iob
  35. * structure for which this was originally written.
  36. * Only some places in __strout have comments to mark modifications.  There
  37. * wasn't time to comment all of them.
  38. *
  39.    XDEF   _u5printf
  40.    XDEF   _u5fprintf
  41.    XDEF   _u5sprintf
  42.    XDEF   _gcvt
  43. * make functions visible to outside world.
  44.    XREF   __iob
  45.    XREF   __flsbf
  46.    XREF   _ecvt
  47. * use above functions from Lattice libraries.
  48. * called with u5printf(<format_string>,<arglist>)
  49. _u5printf:
  50.        link   a6,#-4
  51.        move.l   #__iob+$14,(sp)   * modified from __iob+10, Lattice iob is
  52. *                                   bigger and has different elements.
  53.        pea   12(a6)               * address of first value to print on stack
  54.        move.l   8(a6),-(sp)       * address of the format control string.
  55.        bsr.l   __doprnt           * let __doprnt do all the work.
  56.        addq.l   #8,sp
  57.        move.b   __iob+$20,d0      * modified from __iob+$C, this is where
  58. *                                 * the error flag, if any is kept.
  59.        ext.l   d0                 * also return status code to the caller.
  60.        btst   #5,d0               * 2^5 (32) is an error indicator.
  61.        beq.s   u5pr30             * no error.
  62.        moveq.l   #-1,d0           * oops, user screwed up, signal error.
  63. u5pr2c:
  64.        unlk   a6
  65.        rts
  66. u5pr30:
  67.        moveq.l   #0,d0            * signal no error.
  68.        bra.s   u5pr2c
  69. *
  70. * called with  u5fprintf(<stream>,<format_string>,<arg_list>)
  71. *
  72. _u5fprintf:
  73.        link   a6,#-4
  74.        move.l   8(a6),(sp)        * address of stream.
  75.        pea   16(a6)               * address of first value to print.
  76.        move.l   12(a6),-(sp)      * address of format string.
  77.        bsr.s   __doprnt           * we're tired today, __doprnt do it!
  78.        addq.l   #8,sp
  79.        movea.l   8(a6),a0
  80.        move.w   12(a0),d0
  81.        ext.l   d0
  82.        btst   #5,d0               * did fprintf fail?  
  83.        beq.s   u5fpr2e
  84.        moveq.l   #-1,d0           * yes signal an error to unfortunate user
  85. u5fpr2a:
  86.        unlk   a6
  87.        rts
  88. u5fpr2e:
  89.        moveq.l   #0,d0
  90.        bra.s   u5fpr2a
  91. *
  92. * called with u5sprintf(<addr_of_buf>,<format_string>,<arg_list>)
  93. *
  94. _u5sprintf:
  95.        link   a6,#-16
  96.        moveq.l   #$42,d0
  97.        move.w   d0,-4(a6)
  98.        move.l   8(a6),-12(a6)
  99.        move.l   #$7fff,-16(a6)
  100.        pea   -16(a6)
  101.        pea   16(a6)
  102.        move.l   12(a6),-(sp)
  103.        bsr.s   __doprnt
  104.        lea   12(sp),sp
  105.        subq.l   #1,-16(a6)
  106.        blt.s   u5spr48
  107.        move.l   -12(a6),d0           * skip one past end of string and
  108.        addq.l   #1,-12(a6)           * make sure it is terminated by a
  109.        movea.l   d0,a0               * hex 00 character.
  110.        moveq.l   #0,d0
  111.        move.b   d0,(a0)              * now it is.
  112.        ext.w   d0
  113.        ext.l   d0
  114.        bra.s   u5spr58
  115. u5spr48:
  116.        pea   -16(a6)
  117.        moveq.l   #0,d0               * flush the buffer to the null port 
  118.        move.l   d0,-(sp)             * since doprnt actually puts stuff in
  119.        jsr   __flsbf                 * buffer and we let it do all the work.
  120.        addq.l   #8,sp
  121. u5spr58:
  122.        move.l   8(a6),d0
  123.        unlk   a6
  124.        rts
  125. *
  126. * The workhorse of this whole show.
  127. * Just muddle through the format string a char at a time looking for
  128. * % format specifiers and backslash  \n,\t,\e  etc to handle the special
  129. * characters.
  130. *
  131. __doprnt:
  132.        link   a6,#-164
  133.        movem.l   d0/d2-d7/a2-a5,-(sp)
  134.        movea.l   8(a6),a5            * address of the format string
  135.        movea.l   12(a6),a4           * list head of argument list
  136.        movea.l   16(a6),a3           * address of our buffer (__iob)
  137. dop18:
  138.        lea   -140(a6),a0
  139.        movea.l   a0,a2               * start address of our work buffer.
  140.        bra.l   dop44c                * make sure format string isn't null.
  141. dop22:
  142.        move.b   d7,(a2)+             * top of loop that puts chars in buff.
  143.        bra.l   dop44c
  144. dop28:
  145.        moveq.l   #$25,d0             * is it a %?
  146.        cmp.b   d7,d0
  147.        bne.s   dop22                 * no, its something else so buf it.
  148.        lea   -140(a6),a0             * address of buffer.
  149.        cmpa.l   a0,a2                * have we actually written anything yet?
  150.        beq.s   dop58                 * no we haven't.
  151.        move.l   a3,(sp)              * address of destination buffer.
  152.        moveq.l   #0,d0               * 0 for strout.
  153.        move.l   d0,-(sp)
  154.        lea   -140(a6),a0             * address of our work buffer.
  155.        move.l   a2,d0
  156.        sub.l   a0,d0                 * get length of string so far.
  157.        move.l   d0,-(sp)
  158.        pea   -140(a6)                * plus address of buffer.
  159.        bsr.l   __strout              * tally ho!
  160.        lea   12(sp),sp
  161.        lea   -140(a6),a0
  162.        movea.l   a0,a2
  163. dop58:
  164.        moveq.l   #0,d0
  165.        move.b   d0,-152(a6)          * assume no left justification.
  166.        moveq.l   #0,d4
  167.        moveq.l   #$20,d0
  168.        move.b   d0,-151(a6)
  169.        moveq.l   #$2D,d0             * is it a -, (left justification)
  170.        cmp.b   (a5),d0
  171.        bne.s   dop72                 * no its not.
  172.        addq.b   #1,-152(a6)          * signal left justify needed.
  173.        addq.l   #1,a5                * point to next char in format str.
  174. dop72:
  175.        moveq.l   #$30,d0             * is it a 0?
  176.        cmp.b   (a5),d0
  177.        bne.s   dop7e                 * no.
  178.        move.b   d0,-151(a6)
  179.        addq.l   #1,a5
  180. dop7e:
  181.        moveq.l   #$2A,d0             * is it an asterisk.
  182.        cmp.b   (a5),d0               * if it is handle run-time field
  183.        beq.s   dopa4                 * width/precision specification.s
  184.        moveq.l   #0,d5
  185. dop86:
  186.        move.b   (a5)+,d0             * eat up the digits of a field width
  187.        ext.w   d0                    * precision spec.
  188.        moveq.l   #$30,d1             * do a simple:
  189.        sub.w   d1,d0                 * val=10*val + a5++ until we find
  190.        ext.l   d0                    * something that's not a digit.
  191.        move.l   d0,d6
  192.        blt.s   dopb4                 * something less than 0? exit.
  193.        moveq.l   #9,d0
  194.        cmp.l   d6,d0
  195.        blt.s   dopb4                 * something greater than 9? exit
  196.        add.l   d5,d5                 * multiply by 10.
  197.        add.l   d5,d6
  198.        asl.l   #2,d5
  199.        add.l   d6,d5
  200.        bra.s   dop86                 * round and round we go!
  201. dopa4:
  202.        addq.l   #1,a5
  203.        move.b   (a5)+,d0
  204.        ext.w   d0
  205.        moveq.l   #$30,d1
  206.        sub.w   d1,d0
  207.        move.w   d0,d6
  208.        ext.l   d6
  209.        move.l   (a4)+,d5
  210. dopb4:
  211.        moveq.l   #0,d0               * handle the precision part here.
  212.        move.b   d0,-153(a6)          * just like the field width above.
  213.        moveq.l   #$30,d0
  214.        add.l   d0,d6
  215.        moveq.l   #$2E,d0             * look for a decimal point
  216.        cmp.l   d6,d0
  217.        bne.s   dop104                * none, must not be any precision.
  218.        moveq.l   #$2A,d0             * is precision a *
  219.        cmp.b   (a5),d0
  220.        beq.s   dopf4                 * Oh boy, do some more work for stars
  221.        moveq.l   #0,d4
  222.        bra.s   dope0
  223. dopce:
  224.        moveq.l   #9,d0               * eat up the digits.  Yummy!
  225.        cmp.l   d6,d0
  226.        blt.s   dopee
  227.        addq.b   #1,-153(a6)
  228.        add.l   d4,d4
  229.        add.l   d4,d6
  230.        asl.l   #2,d4
  231.        add.l   d6,d4
  232. dope0:
  233.        move.b   (a5)+,d0
  234.        ext.w   d0
  235.        moveq.l   #$30,d1
  236.        sub.w   d1,d0
  237.        ext.l   d0
  238.        move.l   d0,d6
  239.        bge.s   dopce
  240. dopee:
  241.        moveq.l   #$30,d0
  242.        add.l   d0,d6
  243.        bra.s   dop104
  244. dopf4:
  245.        addq.l   #1,a5                * handle star precision.
  246.        move.b   (a5)+,d0
  247.        ext.w   d0
  248.        ext.l   d0
  249.        move.l   d0,d6
  250.        addq.b   #1,-153(a6)
  251.        move.l   (a4)+,d4             * get an arg for it.
  252. dop104:
  253.        move.l   d6,d0
  254.        moveq.l   #$65,d1             * is it a little e?
  255.        cmp.l   d1,d0
  256.        beq.l   dop350                * do e format.
  257.        bgt.s   dop14e
  258.        moveq.l   #$4F,d1             * O format?
  259.        cmp.l   d1,d0
  260.        beq.l   dop1e6
  261.        bgt.s   dop130
  262.        moveq.l   #$25,d1             * another % symbol, means we print one.
  263.        cmp.l   d1,d0                 * literally I mean.
  264.        beq.l   dop448
  265.        moveq.l   #$44,d1             * is it a D format?
  266.        cmp.l   d1,d0
  267.        beq.l   dop1f0                * do %d format for ints.
  268.        moveq.l   #$4C,d1             * is there an l, that means "long".
  269.        cmp.l   d1,d0
  270.        beq.s   dop18e
  271. dop130:
  272.        moveq.l   #$55,d1             * U format.  Unsigned Octal, (weird)
  273.        cmp.l   d1,d0
  274.        beq.s   dop1ae
  275.        moveq.l   #$58,d1             * X format.  Hex Hex Hex.
  276.        cmp.l   d1,d0
  277.        beq.l   dop1ec
  278.        moveq.l   #$63,d1             * C format, its a char!
  279.        cmp.l   d1,d0
  280.        beq.l   dop22c
  281.        moveq.l   #$64,d1             * another d, little this time.
  282.        cmp.l   d1,d0                 * so go to same place as Big D.
  283.        beq.l   dop1f0
  284. dop14e:
  285.        moveq.l   #$6F,d1             * little o, for octal.
  286.        cmp.l   d1,d0
  287.        beq.l   dop1e6
  288.        bgt.s   dop16e
  289.        moveq.l   #$66,d1             * little f, for float ('scuse me)
  290.        cmp.l   d1,d0
  291.        beq.l   dop2ca
  292.        moveq.l   #$67,d1             * little g, float/scientific.
  293.        cmp.l   d1,d0
  294.        beq.l   dop420
  295.        moveq.l   #$6C,d1             * little l, its a long one.
  296.        cmp.l   d1,d0
  297.        beq.s   dop18e
  298. dop16e:
  299.        moveq.l   #$72,d1             * little r, remote string.
  300.        cmp.l   d1,d0
  301.        beq.l   dop2c2
  302.        moveq.l   #$73,d1             * little s, its a string.
  303.        cmp.l   d1,d0
  304.        beq.l   dop29a
  305.        moveq.l   #$75,d1             * little u, unsigned octal again.
  306.        cmp.l   d1,d0
  307.        beq.s   dop1ae
  308.        moveq.l   #$78,d1             * little x, hex.
  309.        cmp.l   d1,d0
  310.        beq.s   dop1ec
  311.        bra.l   dop44c
  312. *
  313. * these are the work routines that format each of the data types.
  314. *
  315. dop18e:
  316.        move.b   (a5)+,d0
  317.        ext.w   d0
  318.        ext.l   d0
  319.        moveq.l   #$64,d1
  320.        cmp.l   d1,d0
  321.        beq.s   dop1f0
  322.        moveq.l   #$6F,d1
  323.        cmp.l   d1,d0
  324.        beq.s   dop1e6
  325.        moveq.l   #$75,d1
  326.        cmp.l   d1,d0
  327.        beq.s   dop1ae
  328.        moveq.l   #$78,d1
  329.        cmp.l   d1,d0
  330.        beq.s   dop1ec
  331.        subq.l   #1,a5
  332. dop1ae:
  333.        move.l   (a4)+,d2
  334.        moveq.l   #$A,d3
  335. dop1b2:
  336.        tst.l   d2
  337.        bne.s   dop1be
  338.        tst.l   d4
  339.        bne.s   dop1be
  340.        moveq.l   #$30,d0
  341.        move.b   d0,(a2)+
  342. dop1be:
  343.        lea   -150(a6),a0
  344.        move.l   a0,-4(a6)
  345.        bra.s   dop210
  346. dop1c8:
  347.        move.l   d3,(sp)
  348.        move.l   d2,-(sp)
  349.        jsr   _uldivr
  350.        addq.l   #4,sp
  351.        move.l   d0,d2
  352.        move.l   _ldivrm,d6
  353.        moveq.l   #$A,d0
  354.        cmp.l   d6,d0
  355.        ble.s   dop202
  356.        moveq.l   #$30,d0
  357.        bra.s   dop204
  358. dop1e6:
  359.        moveq.l   #8,d3
  360. dop1e8:
  361.        move.l   (a4)+,d2
  362.        bra.s   dop1b2
  363. dop1ec:
  364.        moveq.l   #$10,d3
  365.        bra.s   dop1e8
  366. dop1f0:
  367.        moveq.l   #$A,d3
  368.        tst.l   (a4)
  369.        bge.s   dop1e8
  370.        moveq.l   #$2D,d0
  371.        move.b   d0,(a2)+
  372.        move.l   (a4)+,d0
  373.        neg.l   d0
  374.        move.l   d0,d2
  375.        bra.s   dop1b2
  376. dop202:
  377.        moveq.l   #$57,d0
  378. dop204:
  379.        add.l   d6,d0
  380.        movea.l   -4(a6),a0
  381.        move.b   d0,(a0)
  382.        addq.l   #1,-4(a6)
  383. dop210:
  384.        tst.l   d2
  385.        bne.s   dop1c8
  386. dop214:
  387.        lea   -150(a6),a0
  388.        move.l   -4(a6),d0
  389.        cmp.l   a0,d0
  390.        bls.s   dop250
  391.        subq.l   #1,-4(a6)
  392.        movea.l   -4(a6),a0
  393.        move.b   (a0),(a2)+
  394.        bra.s   dop214
  395. dop22c:
  396.        movea.l   a4,a0
  397.        addq.l   #4,a4
  398.        move.l   a0,-4(a6)
  399.        moveq.l   #0,d6
  400.        bra.s   dop24a
  401. dop238:
  402.        move.l   -4(a6),d0
  403.        addq.l   #1,-4(a6)
  404.        movea.l   d0,a0
  405.        move.b   (a0),(a2)+
  406.        bne.s   dop248
  407.        subq.l   #1,a2
  408. dop248:
  409.        addq.l   #1,d6
  410. dop24a:
  411.        moveq.l   #4,d0
  412.        cmp.l   d6,d0
  413.        bgt.s   dop238
  414. dop250:
  415.        lea   -140(a6),a0
  416.        move.l   a0,-4(a6)
  417. dop258:
  418.        move.l   a2,d0
  419.        sub.l   -4(a6),d0
  420.        move.l   d5,d1
  421.        sub.l   d0,d1
  422.        move.l   d1,d6
  423.        bge.s   dop268
  424.        moveq.l   #0,d6
  425. dop268:
  426.        tst.b   -152(a6)
  427.        bne.s   dop274
  428.        move.l   d6,d0
  429.        neg.l   d0
  430.        move.l   d0,d6
  431. dop274:
  432.        move.b   -151(a6),d0
  433.        ext.w   d0
  434.        ext.l   d0
  435.        move.l   d0,(sp)
  436.        move.l   a3,-(sp)
  437.        move.l   d6,-(sp)
  438.        move.l   a2,d0
  439.        sub.l   -4(a6),d0
  440.        move.l   d0,-(sp)
  441.        move.l   -4(a6),-(sp)
  442.        bsr.l   __strout
  443.        lea   16(sp),sp
  444.        bra.l   dop18
  445. dop29a:
  446.        move.l   (a4)+,-4(a6)
  447.        bne.s   dop2a8
  448.        move.l   #__lastbuf+4,-4(a6)
  449. dop2a8:
  450.        move.l   d4,d6
  451.        bne.s   dop2b2
  452.        move.l   #$7fff,d6
  453. dop2b2:
  454.        movea.l   -4(a6),a2
  455. dop2b6: 
  456.        tst.b   (a2)
  457.        beq.s   dop258
  458.        subq.l   #1,d6
  459.        blt.s   dop258
  460.        addq.l   #1,a2
  461.        bra.s   dop2b6
  462. dop2c2:
  463.        movea.l   (a4),a4
  464.        movea.l   (a4)+,a5
  465.        bra.l   dop44c
  466. dop2ca:
  467.        tst.b   -153(a6)
  468.        bne.s   dop2d2
  469.        moveq.l   #6,d4
  470. dop2d2:
  471.        pea   -8(a6)               * do the f specification.
  472.        pea   -12(a6)
  473.        move.l   d4,-(sp)
  474.        move.l   4(a4),-(sp)
  475.        move.l   (a4),-(sp)
  476.        jsr   _ecvt                * kludge, lattice doesn't have fcvt.
  477.        lea   20(sp),sp
  478.        move.l   d0,-4(a6)
  479.        addq.l   #8,a4
  480.        tst.l   -8(a6)
  481.        beq.s   dop2fc
  482.        moveq.l   #$2D,d0          * if num is <0 put a - in front of buf.
  483.        move.b   d0,(a2)+
  484. dop2fc:
  485.        move.l   -12(a6),d6
  486.        bgt.s   dop308
  487.        moveq.l   #$30,d0          * if need to make sure one 0 shows.
  488.        move.b   d0,(a2)+
  489.        bra.s   dop316
  490. dop308:
  491.        movea.l   -4(a6),a0
  492.        move.b   (a0),(a2)+
  493.        addq.l   #1,-4(a6)
  494.        subq.l   #1,d6
  495.        bgt.s   dop308
  496. dop316:
  497.        move.l   d4,d6
  498.        beq.s   dop31e
  499.        moveq.l   #$2E,d0         * place the decimal point in the right spot
  500.        move.b   d0,(a2)+
  501. dop31e:
  502.        move.l   -12(a6),d0
  503.        neg.l   d0
  504.        move.l   d0,-12(a6)
  505.        ble.s   dop338
  506. dop32a:
  507.        subq.l   #1,d6
  508.        blt.s   dop338
  509.        moveq.l   #$30,d0
  510.        move.b   d0,(a2)+
  511.        subq.l   #1,-12(a6)
  512.        bgt.s   dop32a
  513. dop338:
  514.        tst.l   d6
  515.        ble.l   dop250
  516. dop33e:
  517.        subq.l   #1,d6
  518.        blt.l   dop250
  519.        movea.l   -4(a6),a0
  520.        move.b   (a0),(a2)+
  521.        addq.l   #1,-4(a6)
  522.        bra.s   dop33e
  523. dop350:
  524.        tst.b   -153(a6)
  525.        bne.s   dop35a
  526.        moveq.l   #6,d4
  527.        bra.s   dop35c
  528. dop35a:
  529.        addq.l   #1,d4
  530. dop35c:
  531.        pea   -8(a6)               * do e format, see f format above for
  532.        pea   -12(a6)              * some really informative comments.
  533.        move.l   d4,-(sp)
  534.        move.l   4(a4),-(sp)
  535.        move.l   (a4),-(sp)
  536.        jsr   _ecvt
  537.        lea   20(sp),sp
  538.        move.l   d0,-4(a6)
  539.        addq.l   #8,a4
  540.        tst.l   -8(a6)
  541.        beq.s   dop386
  542.        moveq.l   #$2D,d0
  543.        move.b   d0,(a2)+
  544. dop386:
  545.        movea.l   -4(a6),a0
  546.        moveq.l   #$30,d0
  547.        cmp.b   (a0),d0
  548.        bne.s   dop394
  549.        addq.l   #1,-12(a6)
  550. dop394:
  551.        movea.l   -4(a6),a0
  552.        move.b   (a0),(a2)+
  553.        addq.l   #1,-4(a6)
  554.        moveq.l   #$2E,d0
  555.        move.b   d0,(a2)+
  556.        move.l   d4,d6
  557.        bra.s   dop3b0
  558. dop3a6:
  559.        movea.l   -4(a6),a0
  560.        move.b   (a0),(a2)+
  561.        addq.l   #1,-4(a6)
  562. dop3b0:
  563.        subq.l   #1,d6
  564.        bgt.s   dop3a6
  565.        moveq.l   #$65,d0
  566.        move.b   d0,(a2)+
  567.        subq.l   #1,-12(a6)
  568.        tst.l   -12(a6)
  569.        blt.s   dop3c8
  570.        moveq.l   #$2B,d0             * put a + sign if we need one.
  571.        move.b   d0,(a2)+
  572.        bra.s   dop3d6
  573. dop3c8:
  574.        moveq.l   #$2D,d0             * or a - sign.
  575.        move.b   d0,(a2)+
  576.        move.l   -12(a6),d0
  577.        neg.l   d0
  578.        move.l   d0,-12(a6)
  579. dop3d6:
  580.        moveq.l   #$64,d0                * here we make ascii digits by
  581.        move.l   d0,(sp)                 * repeatedly hacking them off by
  582.        move.l   -12(a6),-(sp)           * dividing by 100.
  583.        jsr   _uldivr
  584.        addq.l   #4,sp
  585.        move.l   d0,d6
  586.        beq.s   dop3f2
  587.        move.l   d6,d0
  588.        moveq.l   #$30,d1                * add ascii 0 to value so user 
  589.        add.l   d1,d0                    * can read it and put it in the
  590.        move.b   d0,(a2)+                * output buffer.
  591. dop3f2:
  592.        moveq.l   #$A,d0                 * multiply remainder by 10
  593.        move.l   d0,(sp)
  594.        move.l   _ldivrm,-(sp)
  595.        jsr   _uldivr
  596.        addq.l   #4,sp
  597.        move.l   d0,d6
  598.        beq.s   dop410
  599.        move.l   d6,d0
  600.        moveq.l   #$30,d1                * add ascii 0 to it too.
  601.        add.l   d1,d0
  602.        move.b   d0,(a2)+
  603. dop410:
  604.        move.l   _ldivrm,d0              * do the remainder too.
  605.        moveq.l   #$30,d1
  606.        add.l   d1,d0
  607.        move.b   d0,(a2)+
  608.        bra.l   dop250                   * go around again for next one.
  609. dop420:
  610.        tst.b   -153(a6)
  611.        bne.s   dop428
  612.        moveq.l   #6,d4                  * defaults to 6 digits if no
  613. *                                       * precision was specified.
  614. dop428:
  615.        move.l   a2,(sp)
  616.        move.l   d4,-(sp)
  617.        move.l   4(a4),-(sp)
  618.        move.l   (a4),-(sp)
  619.        jsr   _gcvt                      * handle g format output.
  620.        lea   12(sp),sp                  * not much work here, gcvt does it
  621.        addq.l   #8,a4                   * all for us.
  622. dop43e:
  623.        nop                              * needed because of bug in Amiga
  624.        tst.b   (a2)+                    * assembler which won't let us do
  625.        bne.s   dop43e                   * a short branch to dop43e.  We
  626.        subq.l   #1,a2                   * should be able to.
  627.        bra.l   dop250                   * backup over null byte from gcvt.
  628. dop448:
  629.        moveq.l   #$25,d0                * here is where we output literal %
  630.        move.b   d0,(a2)+
  631. dop44c:
  632.        move.b   (a5)+,d7                * move next char from format string
  633.        bne.l   dop28                    * into d7 to be processed.
  634.        lea   -140(a6),a0
  635.        cmpa.l   a0,a2                   * have we done anything yet?
  636.        beq.s   dop474                   * if no, then skip next part.
  637.        move.l   a3,(sp)                 * we must have some chars ready
  638.        moveq.l   #0,d0                  * so call __strout and let it put
  639.        move.l   d0,-(sp)                * them wherever we are supposed to.
  640.        lea   -140(a6),a0
  641.        move.l   a2,d0
  642.        sub.l   a0,d0
  643.        move.l   d0,-(sp)
  644.        pea   -140(a6)
  645.        bsr.s   __strout                 * go.
  646.        lea   12(sp),sp
  647. dop474:
  648.        addq.l   #4,sp                   * we are done!.  Whew!
  649.        movem.l   (sp)+,a5-a2/d7-d2
  650.        unlk   a6
  651.        rts
  652. *
  653. * strout modified from SUN version to take into account the differences
  654. * in the structure of __iob on the two machines.
  655. *
  656. __strout:
  657.        link   a6,#0
  658.        movem.l   d0/d6-d7/a4-a5,-(sp)
  659.        movea.l   8(a6),a5            * some var from doprnt
  660.        move.l   12(a6),d7            * length of str to print
  661.        move.l   16(a6),d6            * 0 ?
  662.        movea.l   20(a6),a4           * address of stdout's iobuf
  663.        bra.s   str5e
  664. str1e:
  665.        move.l   a4,(sp)
  666.        move.b   (a5)+,d0
  667.        ext.w   d0
  668.        ext.l   d0
  669.        move.l   d0,-(sp)
  670.        jsr   __flsbf
  671.        addq.l   #4,sp
  672. str30:
  673.        subq.l   #1,d7
  674. str32:
  675.        subq.l   #1,4(a4)            * modified to subtract from wcnt?
  676.        blt.s   str4e                * it used to read  subq.l  #1,(a4)
  677.        move.l   24(a6),d0
  678.        move.l   8(a4),d1            * modified to access the *base of __iob
  679.        addq.l   #1,8(a4)            * this modified too, from 4 to 8.
  680.        movea.l   d1,a0
  681.        move.b   d0,(a0)
  682.        move.b   (a0),d0
  683.        ext.w   d0
  684.        ext.l   d0
  685.        bra.s   str5c
  686. str4e:
  687.        move.l   a4,(sp)              * got some chars so flush the buffer.
  688.        move.l   24(a6),-(sp)
  689.        jsr   __flsbf
  690.        addq.l   #4,sp
  691. str5c:
  692.        addq.l   #1,d6
  693. str5e:
  694.        tst.l   d6
  695.        bge.l   strbe
  696.        moveq.l   #$2D,d0
  697.        cmp.b   (a5),d0
  698.        bne.s   str32
  699.        moveq.l   #$30,d0
  700.        cmp.l   24(a6),d0
  701.        bne.s   str32
  702.        subq.l   #1,4(a4)             * modified from subq.l  #1,(a4)
  703.        blt.s   str1e
  704.        move.b   (a5)+,d0
  705.        ext.w   d0
  706.        ext.l   d0
  707.        move.l   8(a4),d1             * modified from move.l 4(a4),d1
  708.        addq.l   #1,8(a4)             * modified from addq.l #1,4(a4)
  709.        movea.l   d1,a0
  710.        move.b   d0,(a0)
  711.        move.b   (a0),d0
  712.        ext.w   d0
  713.        ext.l   d0
  714.        bra.s   str30
  715. str8e:
  716.        move.b   (a5)+,d0
  717.        ext.w   d0
  718.        ext.l   d0
  719.        move.l   8(a4),d1            * modified from move.l 4(a4),d1
  720.        addq.l   #1,8(a4)            * modified from addq.l #1,4(a4)
  721.        movea.l   d1,a0
  722.        move.b   d0,(a0)
  723.        move.b   (a0),d0
  724.        ext.w   d0
  725.        ext.l   d0
  726.        bra.s   strbe
  727. stra8:
  728.        subq.l   #1,4(a4)            * modified from subq.l #1,(a4)
  729.        bge.s   str8e
  730.        move.l   a4,(sp)
  731.        move.b   (a5)+,d0
  732.        ext.w   d0
  733.        ext.l   d0
  734.        move.l   d0,-(sp)
  735.        jsr   __flsbf
  736.        addq.l   #4,sp
  737. strbe:
  738.        subq.l   #1,d7
  739.        bge.s   stra8
  740.        bra.s   strf0
  741. strc4:
  742.        subq.l   #1,4(a4)            * modified from subq.l #1,(a4)
  743.        blt.s   stre0
  744.        move.l   24(a6),d0
  745.        move.l   8(a4),d1            * modified from move.l 4(a4),d1
  746.        addq.l   #1,8(a4)            * modified from addq.l #1,4(a4)
  747.        movea.l   d1,a0
  748.        move.b   d0,(a0)
  749.        move.b   (a0),d0
  750.        ext.w   d0
  751.        ext.l   d0
  752.        bra.s   stree
  753. stre0:
  754.        move.l   a4,(sp)
  755.        move.l   24(a6),-(sp)
  756.        jsr   __flsbf
  757.        addq.l   #4,sp
  758. stree:
  759.        subq.l   #1,d6
  760. strf0:
  761.        tst.l   d6
  762.        bne.s   strc4
  763.        addq.l   #4,sp
  764.        movem.l   (sp)+,a6-a4/d7-d6
  765.        rts
  766. *
  767. * support routine.  Do unsigned long divide with remainder.  remainder is
  768. * left in location _ldivrm.
  769. *
  770. _uldivr:
  771.        moveq.l   #0,d1
  772.        move.w   4(sp),d1
  773.        divu   10(sp),d1
  774.        move.w   d1,d0
  775.        move.w   6(sp),d1
  776.        divu   10(sp),d1
  777.        swap   d0
  778.        move.w   d1,d0
  779.        clr.w   d1
  780.        swap   d1
  781.        move.l   d1,_ldivrm
  782.        rts
  783. *
  784. * implementation of the gcvt() library routine.  (See gcvt(3C) for details.)
  785. *
  786. * gcvt uses a user provided buffer unlike ecvt and fcvt which use a static
  787. * buffer that is overwritten with each call.  Unfortunately gcvt calls
  788. * ecvt so that if you are mixing calls to ecvt and gcvt your last result
  789. * from ecvt will still be overwritten when you call gcvt.  Tough toenails!
  790. *
  791. _gcvt:
  792.        link   a6,#-12
  793.        movem.l   d0/d7/a4-a5,-(sp)
  794.        pea   -4(a6)
  795.        pea   -8(a6)
  796.        move.l   16(a6),-(sp)
  797.        move.l   12(a6),-(sp)
  798.        move.l   8(a6),-(sp)
  799.        jsr   _ecvt                * let ecvt have its shot at it first.
  800.        lea   20(sp),sp
  801.        movea.l   d0,a5            * address of the result buf.
  802.        movea.l   20(a6),a4
  803.        tst.l   -4(a6)
  804.        beq.s   gcv3a
  805.        moveq.l   #$2D,d0
  806.        move.b   d0,(a4)+
  807. gcv3a:
  808.        move.l   16(a6),d0
  809.        subq.l   #1,d0
  810.        move.l   d0,d7
  811.        bra.s   gcv52
  812. gcv44:
  813.        moveq.l   #$30,d0
  814.        cmp.b   0(a5,d7.l),d0
  815.        bne.s   gcv56
  816.        subq.l   #1,16(a6)
  817.        subq.l   #1,d7
  818. gcv52:
  819.        tst.l   d7
  820.        bgt.s   gcv44
  821. gcv56:
  822.        tst.l   -8(a6)
  823.        blt.s   gcv6a
  824.        move.l   -8(a6),d0
  825.        sub.l   16(a6),d0                * see if there is enough precision
  826.        moveq.l   #4,d1                  * in the -ddd.ddd format, otherwise
  827.        cmp.l   d0,d1                    * we'll have to use scientific
  828.        blt.s   gcv78                    * notation.
  829. gcv6a:
  830.        tst.l   -8(a6)
  831.        bge.l   gcve8
  832.        moveq.l   #-3,d0                 * if exponent <= -4 then we need
  833.        cmp.l   -8(a6),d0                * to use e format to get the 
  834.        ble.l   gcve8                    * maximum precision.
  835. gcv78:
  836.        subq.l   #1,-8(a6)
  837.        move.b   (a5)+,(a4)+
  838.        moveq.l   #$2E,d0                * ecvt doesn't put in decimal point
  839.        move.b   d0,(a4)+                * so we have to do it ourselves.
  840.        moveq.l   #1,d7
  841.        bra.s   gcv8a
  842. gcv86:
  843.        move.b   (a5)+,(a4)+
  844.        addq.l   #1,d7
  845. gcv8a:
  846.        cmp.l   16(a6),d7
  847.        blt.s   gcv86
  848.        moveq.l   #$65,d0
  849.        move.b   d0,(a4)+
  850.        tst.l   -8(a6)
  851.        bge.s   gcva8
  852.        move.l   -8(a6),d0
  853.        neg.l   d0                       * negate the number and put in our
  854.        move.l   d0,-8(a6)               * own minus sign.
  855.        moveq.l   #$2D,d0                * minus sign is aimed and ready!
  856.        move.b   d0,(a4)+
  857.        moveq.l   #$A,d0
  858.        move.l   d0,(sp)
  859.        move.l   -8(a6),-(sp)
  860.        jsr   ldivll
  861.        addq.l   #4,sp
  862.        tst.l   d0
  863.        ble.s   gcvd2
  864. gcva8:
  865.        moveq.l   #$A,d0
  866.        move.l   d0,(sp)
  867.        move.l   -8(a6),-(sp)
  868.        jsr   ldivll
  869.        addq.l   #4,sp
  870.        moveq.l   #$30,d1
  871.        add.l   d1,d0
  872.        move.b   d0,(a4)+
  873. gcvd2:
  874.        moveq.l   #$A,d0
  875.        move.l   d0,(sp)
  876.        move.l   -8(a6),-(sp)
  877.        jsr   lremll
  878.        addq.l   #4,sp
  879.        moveq.l   #$30,d1
  880.        add.l   d1,d0
  881.        bra.l   gcv13c
  882. gcve8:
  883.        tst.l   -8(a6)
  884.        bgt.s   gcvfc
  885.        moveq.l   #$30,d0
  886.        move.b   d0,(a4)+
  887.        moveq.l   #$2E,d0
  888. gcvf4:
  889.        move.b   d0,(a4)+
  890.        tst.l   -8(a6)
  891.        blt.s   gcv100
  892. gcvfc:
  893.        moveq.l   #1,d7
  894.        bra.s   gcv116
  895. gcv100:
  896.        addq.l   #1,-8(a6)
  897.        moveq.l   #$30,d0
  898.        bra.s   gcvf4
  899. gcv108:
  900.        move.b   (a5)+,(a4)+
  901.        cmp.l   -8(a6),d7
  902.        bne.s   gcv114
  903.        moveq.l   #$2E,d0
  904.        move.b   d0,(a4)+
  905. gcv114:
  906.        addq.l   #1,d7
  907. gcv116:
  908.        cmp.l   16(a6),d7
  909.        ble.s   gcv108
  910.        move.l   16(a6),d0
  911.        cmp.l   -8(a6),d0
  912.        blt.s   gcv12c
  913.        bra.s   gcv13e
  914. gcv128:
  915.        moveq.l   #$30,d0
  916.        move.b   d0,(a4)+
  917. gcv12c:
  918.        move.l   16(a6),d0
  919.        addq.l   #1,16(a6)
  920.        cmp.l   -8(a6),d0
  921.        blt.s   gcv128
  922.        moveq.l   #$2E,d0
  923. gcv13c:
  924.        move.b   d0,(a4)+
  925. gcv13e:
  926.        moveq.l   #$2E,d0
  927.        cmp.b   -1(a4),d0
  928.        bne.s   gcv14a
  929.        moveq.l   #$30,d0
  930.        move.b   d0,(a4)+
  931. gcv14a:
  932.        moveq.l   #0,d0
  933.        move.b   d0,(a4)
  934.        move.l   20(a6),d0
  935.        addq.l   #4,sp
  936.        movem.l   (sp)+,a5-a4/d7
  937.        unlk   a6
  938.        rts
  939. *
  940. * support routine for gcvt.
  941. * does long divides. (i.e.  32 bit divides)
  942. ldivll:
  943.        lea   4(sp),a0
  944.        movem.l   d2-d4,-(sp)
  945.        move.l   #1,d4
  946.        move.l   (a0),d0
  947.        bge.s   ldv1a
  948.        neg.l   d0
  949.        neg.w   d4
  950. ldv1a:
  951.        move.l   d0,d2
  952.        move.l   20(sp),d1
  953.        bge.s   ldv26
  954.        neg.l   d1
  955.        neg.w   d4
  956. ldv26:
  957.        move.l   d1,d3
  958.        cmpi.l   #$10000,d1
  959.        bge.s   ldv44
  960.        clr.w   d0
  961.        swap   d0
  962.        divu   d1,d0
  963.        move.w   d0,d3
  964.        move.w   d2,d0
  965.        divu   d1,d0
  966.        swap   d0
  967.        move.w   d3,d0
  968.        swap   d0
  969.        bra.s   ldv6c
  970. ldv44:
  971.        lsr.l   #1,d0
  972.        lsr.l   #1,d1
  973.        cmpi.l   #$10000,d1
  974.        bge.s   ldv44
  975.        divu   d1,d0
  976.        andi.l   #$FFFF,d0
  977.        move.l   d3,d1
  978.        swap   d1
  979.        mulu   d0,d1
  980.        swap   d1
  981.        clr.w   d1
  982.        mulu   d0,d3
  983.        add.l   d3,d1
  984.        cmp.l   d1,d2
  985.        bge.s   ldv6c
  986.        subq.l   #1,d0
  987. ldv6c:
  988.        tst.w   d4
  989.        bge.s   ldv72
  990.        neg.l   d0
  991. ldv72:
  992.        move.l   d0,(a0)
  993.        movem.l   (sp)+,d4-d2
  994.        rts
  995. _ldivrm:    DC.L    0
  996. *
  997. * support routine for gcvt.
  998. * does long remainders, (mod function.)
  999. *
  1000. lremll:
  1001.        lea   4(sp),a0
  1002.        movem.l   d2-d4,-(sp)
  1003.        moveq.l   #1,d4
  1004.        move.l   (a0),d0
  1005.        bge.s   lrm16
  1006.        neg.l   d0
  1007.        neg.l   d4
  1008. lrm16:
  1009.        move.l   d0,d2
  1010.        move.l   20(sp),d1
  1011.        bge.s   lrm20
  1012.        neg.l   d1
  1013. lrm20:
  1014.        cmpi.l   #$10000,d1
  1015.        bge.s   lrm5
  1016.        clr.w   d0
  1017.        swap   d0
  1018.        divu   d1,d0
  1019.        move.w   d2,d0
  1020.        divu   d1,d0
  1021.        clr.w   d0
  1022.        swap   d0
  1023.        bra.s   lrm4
  1024. lrm5:
  1025.        move.l   d1,d3
  1026. lrm3:
  1027.        lsr.l   #1,d0
  1028.        lsr.l   #1,d1
  1029.        cmpi.l   #$10000,d1
  1030.        bge.s   lrm3
  1031.        divu   d1,d0
  1032.        move.l   d3,d1
  1033.        swap   d1
  1034.        mulu   d0,d1
  1035.        mulu   d3,d0
  1036.        swap   d0
  1037.        add.l   d1,d0
  1038.        swap   d0
  1039.        cmp.l   d0,d2
  1040.        bge.s   lrm2
  1041.        sub.l   d3,d0
  1042. lrm2:
  1043.        sub.l   d2,d0
  1044.        neg.l   d0
  1045. lrm4:
  1046.        tst.w   d4
  1047.        bge.s   lrm1
  1048.        neg.l   d0
  1049. lrm1:
  1050.        move.l   d0,(a0)
  1051.        movem.l   (sp)+,d4-d2
  1052.        rts
  1053. *
  1054. * JUNK used by __doprnt on occasion.
  1055. *
  1056. __lastbuf:
  1057.        DC.L     0
  1058.        DC.B     '(nul'
  1059.        DC.B     'l)'
  1060.        DC.B     0
  1061.        DC.B     0
  1062.        DC.L     0,0,0,0,0,0,0,0,0,0
  1063.        DC.L     0,0,0,0,0,0,0,0,0,0
  1064.        DC.L     0,0,0,0,0,0,0,0,0,0
  1065.        DC.L     0,0,0,0,0,0,0,0,0,0
  1066.        DC.L     0,0,0,0,0,0,0,0,0,0
  1067.        DC.L     0,0,0,0,0,0,0,0,0,0
  1068.        DC.L     0,0,0,0,0,0,0,0,0,0
  1069.        DC.L     0,0,0,0,0,0,0,0,0,0
  1070.        DC.L     0,0,0,0,0,0,0,0,0,0
  1071.        DC.L     0,0,0,0,0,0,0,0,0,0
  1072.        DC.L     0,0,0,0,0,0,0,0,0,0
  1073.        DC.L     0,0,0,0,0,0,0,0,0,0
  1074.        DC.L     0,0,0,0,0,0,0,0,0,0
  1075.        DC.L     0,0,0,0,0,0,0,0,0,0
  1076.        DC.L     0,0,0,0,0,0,0,0,0,0
  1077.        DC.L     0,0,0,0,0,0,0,0,0,0
  1078.        DC.L     0,0,0,0,0,0,0,0,0,0
  1079.        DC.L     0,0,0,0,0,0,0,0,0,0
  1080.        DC.L     0,0,0,0,0,0,0,0,0,0
  1081.        DC.L     0,0,0,0,0,0,0,0,0,0
  1082.        END
  1083.